/**
 *
 */
package com.imonsoft.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 文件操作
 * 
 * @author LiQianHui
 * @date 2013-04-17
 * @version 2013
 */
public abstract class FileUtil {
	private final static Log logger = LogFactory.getLog(FileUtil.class);

	/**
	 * This method moves an input file to output file
	 * 
	 * @param String
	 *            input file to move from
	 * @param String
	 *            output file
	 * 
	 */
	public static void move(String input, String output) throws Exception {
		File inputFile = new File(input);
		File outputFile = new File(output);
		try {
			inputFile.renameTo(outputFile);
		} catch (Exception ex) {
			throw new Exception("Can not move " + input + " to " + output + ex.getMessage());
		}
	}

	/**
	 * This method copies an input file to output file
	 * 
	 * @param String
	 *            input file to copy from
	 * @param String
	 *            output file
	 */
	public static boolean copy(String input, String output) throws IOException {
		int BUFSIZE = 65536;// 1024*8*8
		FileInputStream fis = new FileInputStream(input);
		FileOutputStream fos = new FileOutputStream(output);
		try {
			int s;
			byte[] buf = new byte[BUFSIZE];
			while ((s = fis.read(buf)) > -1) {
				fos.write(buf, 0, s);
			}
		} catch (IOException ex) {
			throw new IOException("copy:" + ex.getMessage());
		} finally {
			fis.close();
			fos.close();
		}
		return true;
	}

	public static File makeHome(String home) {
		File homedir = new File(home);
		if (!homedir.exists()) {
			try {
				homedir.mkdirs();
			} catch (SecurityException ex) {
				throw new RuntimeException("Can not mkdir :" + home + ":" + ex.getMessage());
			}
		}
		return homedir;
	}

	/**
	 * This method copies an input files of a directory to another directory not
	 * include subdir
	 * 
	 * @param String
	 *            sourcedir the directory to copy from such as:/home/bqlr/images
	 * @param String
	 *            destdir the target directory
	 */
	public static void copyDir(String sourcedir, String destdir) throws IOException {
		File dest = new File(destdir);
		File source = new File(sourcedir);

		String[] files = source.list();
		try {
			makeHome(destdir);
		} catch (SecurityException ex) {
			logger.error(ex.getMessage());
			throw new IOException("makeHome:" + ex.getMessage());
		}

		for (int i = 0; i < files.length; i++) {
			String sourcefile = source + File.separator + files[i];
			String destfile = dest + File.separator + files[i];
			File temp = new File(sourcefile);
			if (temp.isFile()) {
				try {
					copy(sourcefile, destfile);
				} catch (SecurityException ex) {
					logger.error(ex.getMessage());
					throw new IOException("makeHome:" + ex.getMessage());
				}
			}
		}
	}

	/**
	 * This method del a directory recursively,that means delete all files and
	 * directorys.
	 * 
	 * @param File
	 *            directory the directory that will be deleted.
	 */
	public static void recursiveRemoveDir(File directory) throws IOException {
		if (!directory.exists()) {
			throw new IOException(directory.toString() + " do not exist!");
		}

		String[] filelist = directory.list();
		File tmpFile = null;
		for (int i = 0; i < filelist.length; i++) {
			tmpFile = new File(directory.getAbsolutePath(), filelist[i]);
			if (tmpFile.isDirectory()) {
				recursiveRemoveDir(tmpFile);
			} else if (tmpFile.isFile()) {
				try {
					tmpFile.delete();
				} catch (SecurityException ex) {
					logger.error(ex.getMessage());
					throw new IOException(tmpFile.toString() + " can not be deleted " + ex.getMessage());
				}
			}
		}
		try {
			directory.delete();
		} catch (SecurityException ex) {
			throw new IOException(directory.toString() + " can not be deleted " + ex.getMessage());
		} finally {
			filelist = null;
		}
	}

	public static List<File> findAllFile(String basePath, String suffix) throws IOException {
		List<File> list = new ArrayList<File>();
		File file = new File(basePath);
		if (!file.exists()) {
			throw new IOException(file.toString() + " do not exist!");
		}
		String[] fileList = file.list();
		File tempFile = null;
		String tempPath = null;
		for (String f : fileList) {
			tempFile = new File(file.getAbsoluteFile(), f);
			if (tempFile.isDirectory()) {
				list.addAll(findAllFile(tempFile.getAbsolutePath(), suffix));
			} else if (tempFile.isFile()) {
				tempPath = tempFile.getAbsolutePath();
				if (suffix != null) {
					if (!tempPath.endsWith(suffix)) {
						continue;
					}
				}
				list.add(tempFile);
			}
		}
		return list;
	}

	/**
	 * 根据URL地址得到一个来自互联网上的一个文件
	 * 
	 * @param url
	 * @param path
	 * @param fileName
	 * @throws IOException
	 */
	public static void save(URL url, String path, String fileName) throws IOException {
		FileUtil.makeHome(path);
		BufferedInputStream bis = new BufferedInputStream(url.openStream());
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path + fileName));
		int bytesRead;
		byte[] buffer = new byte[16384];// 16K
		while ((bytesRead = bis.read(buffer, 0, 16384)) != -1) {
			bos.write(buffer, 0, bytesRead);
		}
		bos.flush();
		bos.close();
	}

	/**
	 * 根据输入流来保存一个文件
	 * 
	 * @param is
	 * @param path
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	public static File save(InputStream is, String path, String fileName) throws IOException {
		File file = new File(FileUtil.makeHome(path), fileName);
		BufferedInputStream bis = new BufferedInputStream(is);
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
		try {
			int bytesRead;
			byte[] buffer = new byte[16384];// 16K
			while ((bytesRead = bis.read(buffer, 0, 16384)) != -1) {
				bos.write(buffer, 0, bytesRead);
			}
		} finally {
			bos.flush();
			bos.close();
		}
		return file;
	}

	/**
	 * 给定根目录，返回一个相对路径所对应的实际文件名.
	 * 
	 * @param baseDir
	 *            指定根目录
	 * @param absFileName
	 *            相对路径名，来自于ZipEntry中的name
	 * @return java.io.File 实际的文件
	 */
	public static File getRealFileName(String baseDir, String absFileName) {
		String path = baseDir;
		String file = absFileName;
		int pos = absFileName.lastIndexOf("\\");
		if (pos == -1) {
			pos = absFileName.lastIndexOf("/");
		}
		if (pos != -1) {
			path = baseDir + absFileName.substring(0, pos);
			file = absFileName.substring(pos);
		}
		makeHome(path);
		return new File(path + file);
	}

	public static List<String> file2list(String filePath) {
		BufferedReader bufferedReader = null;
		List<String> list = new ArrayList<String>();
		try {
			bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath))));
			String line = null;
			while ((line = bufferedReader.readLine()) != null) {
				list.add(line.trim());
			}
			bufferedReader.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return list;
	}

	public static void list2file(List<String> list, String filePath) {
		BufferedWriter bufferedWriter = null;
		try {
			bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(filePath))));
			for (String string : list) {
				bufferedWriter.write(string + "\r\n");
			}
			bufferedWriter.flush();
			bufferedWriter.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 判断是WINDOWS系统
	 * 
	 * @return true 表示windows系统
	 */
	public static boolean isWindows() {
		String operatorSystemName = System.getProperty("os.name");
		operatorSystemName = operatorSystemName.toUpperCase();
		if (operatorSystemName.indexOf("WIN") > 0) {
			return true;
		}
		return false;
	}

	public static String getRealPath() {
		String path = FileUtil.class.getResource("").getPath();
		path = path.substring(1, path.indexOf("WEB-INF/"));
		return path;
	}

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		List<File> files = findAllFile("E:/workspace/demo/src/com/qmx/common/util", "java");
		for (File file : files) {
			System.out.println(file.getPath());
			System.out.println(file.getAbsolutePath());
		}
	}
}
